import itertools
import random
import string
import math


class ByteKeyAsciiValueListBuilder(object):
    """build a list of keys
    the keys will be numbers 0 - 255 with (end of text) added"""

    _values_master_list = []

    def __init__(self, value_width, eot_key):
        if type(value_width) is not int:
            raise TypeError
        self._build_key_list(eot_key)
        # always use the same list of chars for values
        if len(ByteKeyAsciiValueListBuilder._values_master_list) == 0:
            last = int(math.ceil(math.sqrt(self._key_len)))
            # the values master list contains enough letters for 2 letter values
            # 3+ letter values require less letters from the alphabet
            # 1 letter values are not supported. there are not 256 letters
            ByteKeyAsciiValueListBuilder._values_master_list = random.sample(list(string.ascii_letters), last)
        self._build_value_list(value_width)
    
    def _build_key_list(self, eot_key):
        self._key_list = [i for i in range(0,256)]
        self._key_list.append(eot_key)
        self._key_len = len(self._key_list)
    
    def _build_value_list(self, value_width):
        self._value_list = []
        last = int(math.ceil(math.sqrt(self._key_len)))
        if value_width < 2:
            value_width = 2
        if value_width == 2:
            value_chars = ByteKeyAsciiValueListBuilder._values_master_list
            random.shuffle(value_chars)
        elif value_width >= 3:
            # 6 ~ cube root of 258
            for nchars in range(6,last,1):
                if nchars ** value_width >= self._key_len:
                    break
            value_chars = random.sample(ByteKeyAsciiValueListBuilder._values_master_list, nchars)
        itr = itertools.product(value_chars, repeat = value_width)
        for i in itr:
            self._value_list.append("".join(i))
        
    def get_shuffled_key_list(self):
        key_list = self._key_list[:]
        random.shuffle(key_list)
        return key_list

    def get_shuffled_value_list(self):
        return random.sample(self._value_list, self._key_len)



class ByteKeyByteValueListBuilder(object):
    """build a list of keys
    the keys will be numbers 0 - 255"""

    def __init__(self):
        self._key_list = [i for i in range(0,256)]
    
    def get_shuffled_key_list(self):
        key_list = self._key_list[:]
        random.shuffle(key_list)
        return key_list

    def get_shuffled_value_list(self):
        return self.get_shuffled_key_list()

